/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#include "TimingWheel.h"

NahidaProject::TimingWheel::TimingWheel(size_t wheelSize, size_t resolutionMs) : wheelSize(wheelSize), resolutionMs(resolutionMs), stop(false) {
	wheel.resize(wheelSize);
	schedulerThread = std::thread(&TimingWheel::Run, this);
}

NahidaProject::TimingWheel::~TimingWheel() {
	stop = true;
	cv.notify_all();
	schedulerThread.join();
}


void NahidaProject::TimingWheel::Schedule(const Task& task, size_t delayMs) {
	std::lock_guard<std::mutex> lock(mutex);
	size_t ticks = (currentTick + (delayMs / resolutionMs)) % wheelSize;
	wheel[ticks].push_back(task);
	cv.notify_one();
}

void NahidaProject::TimingWheel::Run() {
	while (!stop) {
		auto now = Clock::now();
		auto nextTick = now + std::chrono::milliseconds(resolutionMs);

		{
			std::lock_guard<std::mutex> lock(mutex);
			for (auto& task : wheel[currentTick]) {
				task();
			}
			wheel[currentTick].clear();
			currentTick = (currentTick + 1) % wheelSize;
		}

		std::this_thread::sleep_until(nextTick);
	}
}